React Hooks
何なのか
function componentにstatefulなlogicを持たせられる関数
何しろこれ
stateful logic(やstate)が切り出されたものであり、function componentにくっつけることができるものである
lifecycle methodsに代わるものとか考えちゃうとよくわからなくなる(なった)
なまじuseEffectとuseStateがあるせいでhookとは何かが分かりにくくなってる気がする
で、custom hookの使い所がわからなくなる(なった)
何が嬉しいか
function componentの構造を変えなくて済む
classにしなくて良い
class使うとややこしいからね
thisの扱いとか
イベントハンドラのbindとか
そもそもfunction componentをclassにするにはほぼ全部書き直すことになる
逆も然り
テストが書きやすい
Presentational Componentsとかもwrapper hellに向かう
関心の分離
useStateやuseEffectは複数回使えるので、ロジックごとに呼べば良い
componentDidMountとかは複数ロジックをその中に詰め込む必要があった
複数書いた場合は上から順に実行される
結構好きかもzakuni.icon
function componentでできることによって、ただのJSっぽくなったというか classでlifecycle methods使うのってわかりづらかったんだなあ、ってのがわかった感じ
基本
useStateとuseEffectを使う
React function componentのトップレベルから呼ぶこと
code:公式ドキュメントの例.jsx
import React, { useState, useEffect } from 'react';
function Example() {
useEffect(() => {
document.title = You clicked ${count} times;
});
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
code:stateにarray使うときの例.jsx
addItem = (newItem) => {
setItems([
...items,
newItem
]);
}
lifecycle methodsが複雑化する問題も解決しようとしているのだから、まあ当たり前だ
useEffect使う
useEffect
functional componentが関数として、副作用(effect)がある処理を行う時に使うhook
API呼び出しとか時間の経過とか
引数で渡した関数(effect)がrenderの度に呼ばれる
componentDidMountとかcomponentDidUpdateとかに相当することもこれでやる
あとcomponentWillUnmountにも
マウントされた時と更新された時、とか分けて考えなくて良い
毎回呼んで欲しくない場合は第二引数で制御する
第二引数に渡す配列の中身はrenderの度に比較され、前と同じだったら、effectはスキップされる
第二引数の配列にオブジェクトを渡した場合は、一言で言えばObject.isで判定される
配列に複数要素入れた場合はどれか一つ変わってたら実行される
componentDidMountの如く、初回だけしか実行して欲しくない場合は、第二引数に空の配列を渡す
空の配列は変化しないから
effectから関数をreturnすると、それはcomponentがunmountする時に呼ばれる
callbackにはasyncは使うものじゃない?
componentのlogicを再利用可能な関数として切り出すことができる
stateに関する処理の共通化とか
useで始まる名前で、他のHookを呼ぶ
引数や返り値に決まりはない
呼ばれる度にstateはisolatedで、共有されない
reduxなどのライブラリとは相反する可能性がある componentDidMountとかcomponentDidUpdateに詰め込まれがちだったstateful logicを分割できるようになるという
状態管理系のライブラリも(状態管理を切り出すことで)これらを解決しようとしていた
Hooksは別のアプローチ
多分、component毎のstate管理をしやすくするアプローチ
Custom Hookもロジックを再利用するものであって、stateはシェアされない
ただ、useReducerみたいなHookもあって、ふーむ
でもstoreを一つにするわけではなさそうだし、やっぱり中央管理とは逆っぽいような……?
要するにcomponent毎のlistener(setState)をlistで持って、stateが変わる度に全listenerを呼んでる